﻿using Microsoft.AspNetCore.Mvc;
using System.Text.Json;
using System.Web;
using System.IO;
using System.Text;
using System.Xml;
using System.Net.Sockets;
using Microsoft.Extensions.Logging;

namespace WXWorkAPI_V1.Controllers
{

    [ApiController]
    [Route("MsgCallBack")]
    public class MsgCallBackController : Controller
    {
        [HttpGet]
        public IActionResult Get(
            [FromQuery] string msg_signature,
            [FromQuery] string timestamp,
            [FromQuery] string nonce,
            [FromQuery] string echostr)
        {
            // https://www.hbhcv.com/WxWorkAPI/WWAProxy.php
            try
            {
                Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(WxwCFG.sToken, WxwCFG.sEncodingAESKey, WxwCFG.sCorpID);
                string sVerifyMsgSig = msg_signature;
                string sVerifyTimeStamp = timestamp;
                string sVerifyNonce = nonce;
                string sVerifyEchoStr = HttpUtility.UrlDecode(echostr);

                if (sVerifyEchoStr.IndexOf(" ") >= 0)
                    sVerifyEchoStr = sVerifyEchoStr.Replace(" ", "+");

                if (sVerifyEchoStr.IndexOf(@"\u002B") >= 0)
                    sVerifyEchoStr = sVerifyEchoStr.Replace(@"\u002B", "+");

                Dictionary<string, string> tKeys = new Dictionary<string, string>();
                tKeys.Add("timestamp", sVerifyTimeStamp);
                tKeys.Add("nonce", sVerifyNonce);
                string sJSON = JsonSerializer.Serialize(tKeys);
                //System.IO.File.WriteAllText(@"D:\Temp\MsgCallBack.json", sJSON);

                int ret = 0;
                string sEchoStr = "";
                ret = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp, sVerifyNonce, sVerifyEchoStr, ref sEchoStr);
                if (ret != 0)
                {
                    System.Console.WriteLine("ERR: VerifyURL fail, ret: " + ret);
                    return Ok("Error");
                }
                return Ok(sEchoStr);

            }
            catch (Exception ex)
            {
                // 处理异常情况
                return StatusCode(500, $"处理请求时发生错误: {ex.Message}");
            }
        }

        private string sReceMsgXML { get; set; } = "";

        //MsgCallBack?msg_signature=477715d11cdb4164915debcba66cb864d751f3e6&timestamp=1409659813&nonce=1372623149
        // 处理POST请求（用于接收消息）
        [HttpPost]
        public async Task<IActionResult> Post(
            [FromQuery] string msg_signature,
            [FromQuery] string timestamp,
            [FromQuery] string nonce)
        {
            try
            {
                
                Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(WxwCFG.sToken, WxwCFG.sEncodingAESKey, WxwCFG.sCorpID);
                string sReqMsgSig = msg_signature;
                string sReqTimeStamp = timestamp;
                string sReqNonce = nonce;
                // 1. 手动读取请求体
                using var reader = new StreamReader(Request.Body);
                string sReqData = await reader.ReadToEndAsync();

                /*
                string sToken = "QDG6eK";
                string sCorpID = "wx5823bf96d3bd56c7";
                string sEncodingAESKey = "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C";
                Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID);
                string sReqMsgSig = "477715d11cdb4164915debcba66cb864d751f3e6";
                string sReqTimeStamp = "1409659813";
                string sReqNonce = "1372623149";
                string sReqData = "<xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName><Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt><AgentID><![CDATA[218]]></AgentID></xml>";
                 */

                string sMsg = "";  // 解析之后的明文
                int ret = wxcpt.DecryptMsg(sReqMsgSig, sReqTimeStamp, sReqNonce, sReqData, ref sMsg);
                if (ret != 0)
                {
                    //System.Console.WriteLine("ERR: Decrypt Fail, ret: " + ret);
                    return Ok("ERR: Decrypt Fail, ret: " + ret);
                }
                // 将收到的信息发送到TCP服务器
                WxwCFG.thdSendToTcpServer(sMsg);

                // 发送到TCP服务器并获取响应
                //await SendToTcpServerAsync(sMsg);

                /*
                 <xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName>
                 <FromUserName><![CDATA[mycreate]]></FromUserName>
                 <CreateTime>1409659813</CreateTime>
                 <MsgType><![CDATA[text]]></MsgType>
                 <Content><![CDATA[hello]]></Content>
                 <MsgId>4561255354251345929</MsgId>
                 <AgentID>218</AgentID>
                 </xml>


                <xml>
                <ToUserName><![CDATA[ww3521e4dd5090a42e]]></ToUserName>
                <FromUserName><![CDATA[LiMing]]></FromUserName>
                <CreateTime>1748399216</CreateTime>
                <MsgType><![CDATA[text]]></MsgType>
                <Content><![CDATA[测试1]]></Content>
                <MsgId>7509317456232174669</MsgId>
                <AgentID>1000003</AgentID>
                </xml>

                <xml>
                <ToUserName><![CDATA[ww3521e4dd5090a42e]]></ToUserName>
                <FromUserName><![CDATA[LiMing]]></FromUserName>
                <CreateTime>1748399316</CreateTime>
                <MsgType><![CDATA[text]]></MsgType>
                <Content><![CDATA[[微笑]]]></Content>
                <MsgId>7509317885783294029</MsgId>
                <AgentID>1000003</AgentID>
                </xml>


                <xml>
                <ToUserName><![CDATA[ww3521e4dd5090a42e]]></ToUserName>
                <FromUserName><![CDATA[LiMing]]></FromUserName>
                <CreateTime>1748399364</CreateTime>
                <MsgType><![CDATA[image]]></MsgType>
                <PicUrl><![CDATA[https://wework.qpic.cn/wwpic3az/498055_RDTopAdTS4eM5aX_1748399364/]]></PicUrl>
                <MsgId>7509318090355952717</MsgId>
                <MediaId><![CDATA[13pU-WSfFi0riBVlFaXgLnpSQ5l3sVbfroIypILrjtIjkZNCuD0-rapWX7bWbkprs]]></MediaId>
                <AgentID>1000003</AgentID>
                </xml>

                <xml>
                <ToUserName><![CDATA[ww3521e4dd5090a42e]]></ToUserName>
                <FromUserName><![CDATA[LiMing]]></FromUserName>
                <CreateTime>1748477213</CreateTime>
                <MsgType><![CDATA[voice]]></MsgType>
                <MediaId><![CDATA[17l0LlotRBcrAcMkZTpEahD712dBcXZVv7iutnymA19g_uQMXrkL_2w4f2iL3fl-r]]></MediaId>
                <Format><![CDATA[amr]]></Format>
                <MsgId>7509652447758670925</MsgId>
                <AgentID>1000003</AgentID>
                </xml>
                 */

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(sMsg);
                XmlNode root = doc.FirstChild;
                string sJSON = "";
                string sToUserName = "";
                string sFromUserName = "";
                Dictionary<string, string> tInfo = new Dictionary<string, string>();
                if (root["ToUserName"] != null)
                {
                    sToUserName = root["ToUserName"].InnerText;
                    tInfo.Add("ToUserName", root["ToUserName"].InnerText);
                }
                if (root["FromUserName"] != null)
                {
                    sFromUserName = root["FromUserName"].InnerText;
                    tInfo.Add("FromUserName", root["FromUserName"].InnerText);
                }
                if (root["CreateTime"] != null)
                    tInfo.Add("CreateTime", root["CreateTime"].InnerText);
                if (root["MsgType"] != null)
                    tInfo.Add("MsgType", root["MsgType"].InnerText);
                if (root["MsgId"] != null)
                    tInfo.Add("MsgId", root["MsgId"].InnerText);
                if (root["AgentID"] != null)
                    tInfo.Add("AgentID", root["AgentID"].InnerText);
                if (root["Content"] != null)
                    tInfo.Add("Content", root["Content"].InnerText);
                else
                    root.AppendChild(doc.CreateElement("Content"));
                sJSON = JsonSerializer.Serialize(tInfo);

                if (root["MediaId"] != null)
                {
                    root.RemoveChild(root["MediaId"]);
                }
                if  (root["Format"] != null)
                {
                    root.RemoveChild(root["Format"]);
                }

                /*
                //string sRespData = "
                <xml>
                <ToUserName><![CDATA[mycreate]]></ToUserName>
                <FromUserName><![CDATA[wx582396d3bd56c7]]></FromUserName>
                <CreateTime>1348831860</CreateTime>
                <MsgType><![CDATA[text]]></MsgType>
                <Content><![CDATA[this is a test]]></Content>
                <MsgId>1234567890123456</MsgId>
                <AgentID>128</AgentID>
                </xml>";
                */

                root["ToUserName"].InnerText = "";
                root["FromUserName"].InnerText = "";
                root["MsgType"].InnerText = "";
                root["Content"].InnerText = "";

                XmlCDataSection cdataToUserName = doc.CreateCDataSection(sFromUserName);
                root["ToUserName"].AppendChild(cdataToUserName);
                XmlCDataSection cdataFromUserName = doc.CreateCDataSection(sToUserName);
                root["FromUserName"].AppendChild(cdataFromUserName);
                XmlCDataSection cdataFromMsgType = doc.CreateCDataSection("text");
                root["MsgType"].AppendChild(cdataFromMsgType);
                XmlCDataSection cdataContent = doc.CreateCDataSection("正在思考，请稍等...");
                root["Content"].AppendChild(cdataContent);

                StringBuilder xmlString = new StringBuilder();

                using (StringWriter sw = new StringWriter(xmlString))
                {
                    // 配置XmlWriterSettings
                    XmlWriterSettings settings = new XmlWriterSettings
                    {
                        OmitXmlDeclaration = true,  // 禁用XML声明(<?xml version="1.0" encoding="utf-16"?>)
                        Indent = false              // 可选：格式化输出
                    };

                    using (XmlWriter writer = XmlWriter.Create(sw, settings))
                    {
                        doc.Save(writer);
                    }
                }
                //await SendToTcpServerAsync(xmlString.ToString());

                string sEncryptMsg = "";
                ret = wxcpt.EncryptMsg(xmlString.ToString(), sReqTimeStamp, sReqNonce, ref sEncryptMsg);
                if (ret != 0)
                {
                    return Ok("ERR: EncryptMsg Fail, ret: " + ret);
                }
                //await SendToTcpServerAsync(sEncryptMsg);

                // 5. 返回成功响应
                return Ok(sEncryptMsg);
            }
            catch (Exception ex)
            {
                WxwCFG.thdSendToTcpServer($"Error[MsgCallBack@Post]: {ex.Message}");
                // 记录详细错误日志
                return StatusCode(500, $"处理POST请求时发生错误: {ex.Message}");
            }
        }
    }
}
